#include <iostream>
#include <list>
#include <stdlib.h>
#include <time.h>

#include "function.h"
#include "parser.h"

using namespace std;


void printOrderings (CallGraph::Enumeration& en) 
{                   
    while (en.HasMoreElements()) {
        list<Function*>& calls = en.NextElement();
            
        printf ("\n");
        list<Function*>::iterator it = calls.begin();
        while (it != calls.end()) {
            printf ("%s ", (*it)->name);
            fflush (stdout);
            it++;
        }        
        printf ("\n");
    }
}

void test1() {    
    
    Function foo1 ("foo1");
    Function foo2 ("foo2");
    Function g ("g");    
    Function h ("h");  
    Function f ("f");
    
    foo2.dependencies = 0;
    g.dependencies = 1;
    h.dependencies = 1;
    foo1.dependencies = 1;
    f.dependencies = 1;
    
    foo2.AddDependent (&h);
    foo2.AddDependent (&g);
    g.AddDependent (&foo1);
    foo1.AddDependent (&f);
    
    CallGraph::Enumeration en (&foo2);
    printOrderings (en);
}


void test2() {    
    
    Function a ("a");
    Function b ("b");
    Function c ("c");    
    Function d ("d");  
    Function e ("e");  
    Function f ("f");
    
    a.dependencies = 0;
    b.dependencies = 2;
    c.dependencies = 1;
    d.dependencies = 2;
    e.dependencies = 1;
    f.dependencies = 1;
    
    a.AddDependent (&b);
    a.AddDependent (&c);
    a.AddDependent (&d);
    a.AddDependent (&f);
    c.AddDependent (&e);
    d.AddDependent (&b);
    e.AddDependent (&d);
    
    CallGraph::Enumeration en (&a);
    printOrderings (en);
}


void test3() {    
    Function z ("z");
    Function a ("a");
    Function b ("b");
    Function c ("c");    
    Function d ("d");  
    Function e ("e");  
    Function f ("f");
    
    z.dependencies = 0;
    a.dependencies = 0;
    b.dependencies = 2;
    c.dependencies = 1;
    d.dependencies = 2;
    e.dependencies = 1;
    f.dependencies = 1;
        
    a.AddDependent (&b);
    a.AddDependent (&c);
    a.AddDependent (&d);
    a.AddDependent (&f);
    c.AddDependent (&e);
    d.AddDependent (&b);
    e.AddDependent (&d);
    
    list<Function*> roots;
    roots.push_back (&z);
    roots.push_back (&a);
    
    CallGraph::Enumeration en (roots);
    printOrderings (en);
}

void test4() {    
    
    Function a ("A");
    Function b ("B");
    Function c ("C");    
    Function d ("D");  
    
    a.dependencies = 0;
    b.dependencies = 0;
    c.dependencies = 2;
    d.dependencies = 1;
    
    a.AddDependent (&c);
    b.AddDependent (&c);
    b.AddDependent (&d);
    
    list<Function*> roots;
    roots.push_back (&a);
    roots.push_back (&b);
    
    CallGraph::Enumeration en (roots);
    printOrderings (en);
}

int main(int argc, char **argv) {
    
    /* initialize random seed: */
    srand ( time(NULL) );
  
    std::cout << "\nParsing..." << std::endl;
    
    Parser p ("/home/nico/Projects/FinalTermPA/FinalJune12/build/prova.txt");
    CallGraph* graph = p.Parse();    
    
    std::cout << "Done!\n" << std::endl;
        
    CallGraph::Enumeration en = graph->GetEnumeration();
    printOrderings (en);
    
    int n = 2;
    graph->SetRandomTime();
    graph->Print();
    int totalTime = 0;
    Processor* assignments = graph->Schedule (n);                
    for (int i=0; i<n; i++) {
        printf ("\nProcessor %d: ", i);
        assignments[i].Print();
        int t = assignments[i].GetExecTime();
        totalTime = t > totalTime ? t : totalTime;
    }
    printf ("\nTotal time = %d\n\n", totalTime);
    
    delete graph;
    
//      test4();
    
    return 0;
}
